<template>
  <el-form ref="formRef" class="global-variable-item-wrapper" :model="formData" label-width="auto">
    <el-form-item
      v-for="column in columns"
      :key="column.prop"
      :label="column.label"
      :prop="column.prop"
    >
      <!-- option 组件 -->
      <component
        :is="components[column.type]"
        v-if="components[column.type] && optionComponents[column.type]"
        v-model="formData[column.prop]"
        v-bind="column.formProps"
        @change="handleUpdate"
      >
        <component
          :is="optionComponents[column.type]"
          v-for="option in column.options"
          :key="option.value"
          :value="option.value"
          :label="option.label"
        >
          {{ option.label }}
        </component>
      </component>

      <!-- 普通组件 -->
      <component
        :is="components[column.type]"
        v-else
        v-model="formData[column.prop]"
        v-bind="column.formProps"
        @change="handleUpdate"
      />
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { useEditorStore } from '@/store/editor';
import {
  ElCheckbox,
  ElColorPicker,
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElOption,
  ElSelect,
  ElSlider,
  ElSwitch,
} from 'element-plus';
import { FormControlTypeEnum, VariableTypeOptions } from '../../config';
import { Column } from './typing';

interface IProps {
  data: Record<string, any>;
}

defineOptions({
  name: 'GlobalVariableItem',
});

const props = withDefaults(defineProps<IProps>(), {});
const emits = defineEmits(['update:data', 'variableNameChange']);

const editorStore = useEditorStore();

const formData = ref<Record<string, any>>({
  name: '',
  description: '',
  type: 'string',
  value: '',
  ...props.data,
});

const components: Partial<Record<FormControlTypeEnum, any>> = {
  input: ElInput,
  'input-number': ElInputNumber,
  switch: ElSwitch,
  slider: ElSlider,
  select: ElSelect,
  checkbox: ElCheckbox,
  'color-picker': ElColorPicker,
};

const optionComponents: Partial<Record<FormControlTypeEnum, any>> = {
  select: ElOption,
};

const columns = ref<Column[]>([
  {
    label: '名称',
    prop: 'name',
    type: 'input',
  },
  {
    label: '描述',
    prop: 'description',
    type: 'input',
    formProps: { type: 'textarea' },
  },
  {
    label: '类型',
    prop: 'type',
    type: 'select',
    options: VariableTypeOptions,
    formProps: { placeholder: '请选择' },
  },
  {
    label: '变量值',
    prop: 'value',
    type: formData.value.type,
    formProps: { controls: false, 'show-alpha': true, 'color-format': 'rgb' },
  },
]);

watch(
  () => formData.value.type,
  () => {
    changeVariableValueType();
    formData.value.value = '';
  }
);

const changeVariableValueType = () => {
  const valueColumn = columns.value.find((o) => o.prop === 'value');
  if (!valueColumn) {
    return;
  }
  const selectedVariableType = VariableTypeOptions.find((o) => o.value === formData.value.type)!;
  valueColumn.type = selectedVariableType.formControlType;
};

/**
 * 变量名是否冲突
 */
const variableConflict = () => {
  const index = editorStore.globalVariables
    .filter((o) => o.name !== props.data.name)
    .findIndex((o) => o.name === formData.value.name);
  return index > -1;
};

const handleUpdate = () => {
  // 计算是否重复的变量名，如果是，需要重置回缓存的变量名
  const oldName = props.data.name;
  const newName = formData.value.name;
  if (variableConflict()) {
    formData.value.name = oldName;
    return;
  }
  if (newName !== oldName) {
    emits('variableNameChange', formData.value.name, props.data.name);
  }
  emits('update:data', formData.value);
};

onMounted(() => {
  changeVariableValueType();
});
</script>

<style lang="less" scoped>
.global-variable-item-wrapper {
  :deep(.el-form-item) {
    .el-form-item__content {
      max-width: var(--item-content-width);
    }
    .el-select,
    .el-input-number,
    .el-cascader {
      width: 100%;
    }
  }
  :deep(.footer) {
    width: 100%;
    text-align: center;
  }
}
</style>
